//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Log.print('service module: prosklisi');
Service.prosklisi = {};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Δικαίωμα αποστολής πρόσκλησης έχουν μόνον όσοι συμμετέχουν ως παίκτες στο τραπέζι τη
// στιγμή της αποστολής. Ως παραμέτρους του αιτήματος αποστολής πρόσκλησης καθορίζουμε
// τον κωδικό τραπεζιού ("trapezi") και το login name του προσκεκλημένου ("pros").

Service.prosklisi.apostoli = function(nodereq) {
	var skiniko = nodereq.skinikoGet(), conn, trapezi, pektis, prosklisi, query;

	if (nodereq.isvoli()) return;
	if (nodereq.oxiTrapezi()) return;
	if (!nodereq.url.hasOwnProperty('pros')) return nodereq.end('Ακαθόριστος προσκεκλημένος');

	trapezi = nodereq.trapeziGet();
	pektis = nodereq.loginGet();
	if (!trapezi.thesiPekti(pektis)) return nodereq.end('Δεν έχετε δικαίωμα πρόσκλησης στο τραπέζι');

	// Οι προσκλήσεις καταχωρούνται κατ' αρχάς στην database. Αν αυτό το βήμα αποτύχει
	// το αίτημα ακυρώνεται.

	conn = DB.connection();
	query = 'INSERT INTO `prosklisi` (`trapezi`, `apo`, `pros`) VALUES (' + nodereq.url.trapezi + ', ' +
		globals.json(pektis) + ', ' + globals.json(nodereq.url.pros) + ')';
	conn.queryRaw(query, function(err, res) {
		conn.free();
		if ((!res) || (res.affectedRows != 1)) return nodereq.end('Απέτυχε καταχώρηση της πρόσκλησης στην database');

		// Η πρόσκληση καταχωρήθηκε επιτυχώς στην database και από το σημείο αυτό
		// και μετά η διαδικασία είναι απρόσκοπτη, επομένως κλείνουμε το αίτημα.

		nodereq.end();

		// Εισάγουμε την πρόσκληση στο τραπέζι.

		trapezi.prosklisiAdd(new Prosklisi({
			kodikos: res.insertId,
			trapezi: nodereq.url.trapezi,
			apo: pektis,
			pros: nodereq.url.pros,
		}));

		// Δρομολογούμε ενημέρωση των clients.

		skiniko.kinisiAdd(new Kinisi('PL').set({
			l: res.insertId,
			t: nodereq.url.trapezi,
			a: pektis,
			p: nodereq.url.pros,
		}));
	});
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Η αποδοχή πρόσκλησης γίνεται με κλικ πάνω στο σώμα της πρόσκλησης και διέπεται από
// απλούς κανόνες. Ως "παίκτης" λογίζεται ο παίκτης που αποδέχεται την πρόσκληση, ενώ
// ως "τραπέζι" λογίζεται το τραπέζι της πρόσκλησης. Με λίγα λόγια η διαδικασία είναι
// η εξής: Αν ο παίκτης υφίσταται ήδη ως παίκτης στο τραπέζι δεν χρειάζεται να γίνει
// καμία επιπλέον ενέργεια. Αν υπάρχει κενή θέση στο τραπέζι, ο παίκτης τοποθετείται
// ως παίκτης σε κενή θέση του τραπεζιού, κατά προτίμησιν θέση που σχετίζεται με τον
// παίκτη. Αν δεν υπάρχει κενή θέση στο τραπέζι, τότε ο παίκτης τοποθετείται ως θεατής
// στο τραπέζι.

Service.prosklisi.apodoxi = function(nodereq) {
	var skiniko = nodereq.skinikoGet(), sinedriaPrin, trapeziPrin, pektis, sinedria, trapezi, prosklisi, thesi;

	if (nodereq.isvoli()) return;
	if (!nodereq.url.hasOwnProperty('trapezi')) return nodereq.end('Απροσδιόριστο τραπέζι πρόσκλησης');
	if (!nodereq.url.hasOwnProperty('prosklisi')) return nodereq.end('Απροσδιόριστος κωδικός πρόσκλησης');

	trapezi = skiniko.trapeziGet(nodereq.url.trapezi);
	if (!trapezi) return nodereq.end('Ανυπόστατο τραπέζι πρόσκλησης');

	prosklisi = trapezi.prosklisiGet(nodereq.url.prosklisi);
	if (!prosklisi) return nodereq.end('Ανυπόστατη πρόσκληση');

	pektis = nodereq.loginGet();
	if (prosklisi.prosGet() != pektis) return nodereq.end('Η πρόσκληση δεν σας αφορά');

	sinedria = nodereq.sinedriaGet();
	sinedriaPrin = new Sinedria(sinedria);				// αντίγραφο πριν την αποδοχή
	trapeziPrin = skiniko.trapeziGet(sinedria.trapeziGet());	// τραπέζι πριν την αποδοχή

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@
	// Εξετάζουμε την περίπτωση κατά την οποία ο παίκτης βρίσκεται ήδη στο τραπέζι.

	if (trapeziPrin && (trapeziPrin.kodikosGet() == prosklisi.trapeziGet())) {
		// Εάν ο παίκτης κατέχει ήδη θέση ως παίκτης στο τραπέζι, τότε δεν χρειάζεται
		// να γίνει καμία περαιτέρω ενέργεια.

		if (sinedria.isPektis()) return nodereq.end("Παίζετε ήδη σ' αυτό το τραπέζι");

		// Ο παίκτης είναι θεατής στο τραπέζι, οπότε επιχειρούμε να τον καταστήσουμε
		// παίκτη, ει δυνατόν στην ίδια θέση.

		thesi = sinedria.thesiGet();

		// Αν η θέση θέασης είναι κατειλημμένη, αναζητούμε μια οποιαδήποτε κενή θέση.

		if (trapezi.pektisGet(thesi)) thesi = trapezi.keniThesi();

		// Αν δεν βρέθηκε κενή θέση, έχουμε πρόβλημα.

		if (!thesi) return nodereq.end('Δεν υπάρχει ελεύθερη θέση στο τραπέζι');

		// Βρέθηκε κενή θέση και ο παίκτης θα τοποθετηθεί ως παίκτης σ' αυτή τη θέση.

		return Service.prosklisi.apodoxiPektis(nodereq, pektis, sinedria, trapezi,
			prosklisi, thesi, sinedriaPrin, trapeziPrin);
	}

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@
	// Ο παίκτης βρίσκεται σε άλλο τραπέζι ή είναι περιφερόμενος. Μπορεί, όμως, να κατέχει
	// θέση ως παίκτης στο τραπέζι και αυτό ακριβώς εξετάζουμε τώρα.

	thesi = trapezi.thesiPekti(pektis);
	if (thesi) return Service.prosklisi.apodoxiPektis(nodereq, pektis, sinedria, trapezi,
		prosklisi, thesi, sinedriaPrin, trapeziPrin);

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@
	// Ο παίκτης είναι περιφερόμενος, ή βρίσκεται σε άλλο τραπέζι, και δεν κατέχει θέση
	// ως παίκτης στο τραπέζι τής πρόσκλησης.

	// Ελέγχουμε τυχόν προηγούμενο πέρασμα τού παίκτη από το τραπέζι και βρίσκουμε τη θέση
	// που κατείχε τότε, αλλιώς προτείνουμε την πρώτη θέση.

	thesi = trapezi.protasiThesis(pektis);

	// Αν η προτεινόμενη θέση είναι κατειλημμένη, αναζητούμε μια οποιαδήποτε κενή θέση.

	if (trapezi.pektisGet(thesi)) thesi = trapezi.keniThesi();

	// Αν βρέθηκε κενή θέση, ο παίκτης θα τοποθετηθεί ως παίκτης σ' αυτή τη θέση.

	if (thesi) return Service.prosklisi.apodoxiPektis(nodereq, pektis, sinedria, trapezi,
		prosklisi, thesi, sinedriaPrin, trapeziPrin);

	// Δεν βρέθηκε κενή θέση, επομένως ο παίκτης θα τοποθετηθεί ως θεατής στην πιο
	// κατάλληλη γι' αυτόν θέση.

	thesi = trapezi.protasiThesis(pektis);
	Service.prosklisi.apodoxiTheatis(nodereq, pektis, sinedria, trapezi,
		prosklisi, thesi, sinedriaPrin, trapeziPrin);
}

// Η function που ακολουθεί αποδέχεται την πρόσκληση καθιστώντας τον προσκεκλημένο θεατή
// στο τραπέζι. Αυτό μπορεί να συμβεί όταν δεν υπάρχει κενή θέση στο τραπέζι.

Service.prosklisi.apodoxiTheatis = function(nodereq, pektis, sinedria, trapezi,
	prosklisi, thesi, sinedriaPrin, trapeziPrin) {
	var skiniko = nodereq.skinikoGet();

	// Κλείνουμε το αίτημα αποδοχής.

	nodereq.end();

	// Φροντίζουμε την ακεραιότητα και τη συμβατότητα των στοιχείων του σκηνικού.

	Service.prosklisi.apodoxiCleanup(skiniko, pektis, trapeziPrin);

	// Θέτουμε τα στοιχεία θέσης της συνεδρίας ώστε να καταστεί συνεδρία θεατού
	// στη συγκεκριμένη θέση στο συγκεκριμένο τραπέζι.

	sinedria.setTheatis(trapezi.kodikosGet(), thesi);

	// Ενημερώνουμε τη λίστα θεατών του τραπεζιού.

	trapezi.theatisAdd(pektis, thesi);

	// Κλείνουμε τη διαδικασία αποδοχής της πρόσκλησης.

	Service.prosklisi.apodoxiTelos(skiniko, prosklisi);
}

Service.prosklisi.apodoxiPektis = function(nodereq, pektis, sinedria, trapezi,
	prosklisi, thesi, sinedriaPrin, trapeziPrin) {
	var
	conn = DB.connection(),
	query = 'UPDATE `trapezi` SET `pektis' + thesi + '` = ' + globals.json(pektis) +
		' WHERE `kodikos` = ' + trapezi.kodikosGet();

	conn.queryRaw(query, function(err, res) {
		conn.free();
		if ((!res) || (res.affectedRows != 1)) return nodereq.end('Απέτυχε η τοποθέτηση παίκτη στο τραπέζι');
		Service.prosklisi.apodoxiPektis1(nodereq, pektis, sinedria, trapezi,
			prosklisi, thesi, sinedriaPrin, trapeziPrin);
	});
}

Service.prosklisi.apodoxiPektis1 = function(nodereq, pektis, sinedria, trapezi,
	prosklisi, thesi, sinedriaPrin, trapeziPrin) {
	var skiniko = nodereq.skinikoGet();
	nodereq.end();
	Service.prosklisi.apodoxiCleanup(skiniko, pektis, trapeziPrin);
	sinedria.setPektis(trapezi.kodikosGet(), thesi);
	trapezi.pektisSet(pektis, thesi);
	Service.prosklisi.apodoxiTelos(skiniko, prosklisi);
}

Service.prosklisi.apodoxiCleanup = function(skiniko, pektis, trapeziPrin) {
	skiniko.rebelosDelete(pektis);
	if (trapeziPrin) trapeziPrin.theatisDelete(pektis);
}

Service.prosklisi.apodoxiTelos = function(skiniko, prosklisi) {
	skiniko.kinisiAdd(new Kinisi('AL').set({
		p: prosklisi.prosGet(),
		t: prosklisi.trapeziGet(),
		l: prosklisi.kodikosGet(),
	}));
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Service.prosklisi.diagrafi = function(nodereq) {
	var skiniko = nodereq.skinikoGet(), trapezi, prosklisi, query;

	if (nodereq.isvoli()) return;
	if (!nodereq.url.hasOwnProperty('trapezi')) return nodereq.end('Απροσδιόριστο τραπέζι πρόσκλησης');
	if (!nodereq.url.hasOwnProperty('prosklisi')) return nodereq.end('Απροσδιόριστος κωδικός πρόσκλησης');

	trapezi = skiniko.trapeziGet(nodereq.url.trapezi);
	if (!trapezi) return nodereq.end('Ανυπόστατο τραπέζι πρόσκλησης');

	prosklisi = trapezi.prosklisiGet(nodereq.url.prosklisi);
	if (!prosklisi) return nodereq.end('Ανυπόστατη πρόσκληση');

	query = 'DELETE FROM `prosklisi` WHERE `kodikos` = ' + nodereq.url.prosklisi;
	DB.connection().query(query, function(conn) {
		if (conn.free().affectedRows != 1) return nodereq.end('Απέτυχε η διαγραφή πρόσκλησης');

		nodereq.end();
		trapezi.prosklisiDelete(nodereq.url.prosklisi);
		skiniko.kinisiAdd(new Kinisi('DL').set({
			t: nodereq.url.trapezi,
			l: nodereq.url.prosklisi,
			a: prosklisi.apo,
			p: prosklisi.pros,
		}));
	});
}
